/*
 * Platzad
 * Copyright 2008 Shayne Riley
 *
 * This file is part of Platzad.
 *
 * Platzad is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Platzad is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Platzad.  If not, see <http://www.gnu.org/licenses/>.
 *
 * To contact the authors on questions or issues regarding the license,
 * you may send an email to <shayner at gmail dot com> or write to
 * Shayne Riley / P.O. Box 1092 / McCook, NE 69001.
 */

#include "NetworkSystem.h"
#include <SDL/SDL.h>
#include <SDL/SDL_net.h>
#include <iostream>
#include <string.h>
#include "SDLDelegate.h" // Helps with starting sdl-based systems.

namespace pzdNetwork
{

void NetworkSystem::start()
{
	// Add a mutex here when threaded.

	// Because it is static, the destructor is called automatically at the
	// end of the application or thread or something.
	static NetworkSystem instance;

	// Note that this does not return an instance of the class.
	// This only prepares the system for use.
}

NetworkSystem::NetworkSystem()
{
    init();
}

NetworkSystem::~NetworkSystem()
{
    finalize();
}

void NetworkSystem::finalize()
{
	using namespace std;

    cout << "Closing network subsystem." << endl;

    static bool alreadyShutdown = false;

    if(!alreadyShutdown)
    {
        alreadyShutdown = true;
    	SDLNet_Quit();
    }
    else
    {
        cout << "Network memory was already released." << endl;
    }
    cout << "Network subsystem shut down." << endl;
}

void NetworkSystem::init()
{
	using namespace std;

	cout << "Initializing Network Subsystem." << endl;

	// Initialize SDL core if not already.
	if(!pzd::SDLDelegate::getInstance().needSDL())
	{
		// Failure
		cerr << "SDL not able to initialize, display sub-system cannot "
			<< "initialize." << endl;
		return;
	}

	IPaddress ip;		// Server address
	TCPsocket sd;		// Socket descriptor
	int quit, len;
	char buffer[512];

	if (SDLNet_Init() < 0)
	{
		cerr << "SDLNet_Init: " << SDLNet_GetError() << endl;
		return;
	}

	// Resolve the host we are connecting to
	if (SDLNet_ResolveHost(&ip, "127.0.0.1", 2000) < 0)
	{
		cerr << "SDLNet_ResolveHost: " << SDLNet_GetError() << endl;
		cerr << "This means you should try a different IP address or port."
			<< endl;
		return;
	}

	// Open a connection with the IP provided (listen on the host's port)
	if (!(sd = SDLNet_TCP_Open(&ip)))
	{
		cerr << "SDLNet_TCP_Open: " << SDLNet_GetError() << endl;
		cerr << "Make sure to start the server first." << endl;
		return;
	}

	// Send messages
	quit = 0;
	while (!quit)
	{
		cout << "Write something:" << endl <<">";
		cin >> buffer;

		len = strlen(buffer) + 1;
		if (SDLNet_TCP_Send(sd, (void *)buffer, len) < len)
		{
			cerr << "SDLNet_TCP_Send: " << SDLNet_GetError() << endl;
			cerr << "Did the server die, are you connected to the right port,"
				<< endl;
			cerr << "are you connected to the right IP address? Remember, 0"
				<< endl;
			cerr << "doesn't count as an IP address." << endl;
			return;
		}

		if(strcmp(buffer, "exit") == 0)
			quit = 1;
		if(strcmp(buffer, "quit") == 0)
			quit = 1;
	}

	SDLNet_TCP_Close(sd);
	cout << "Network Subsystem successfully initialized." << endl;
	return;
}

} // namespace
